// Copyright (C) 2025, ZWSOFT Co., LTD.(Guangzhou)
// Licensed under the MIT License. See LICENSE in the project root for license information.

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using TestClient.Domain;

namespace TestClient.ViewModel;

public enum TestResult
{
    Unknown = -1,
    Pending = 0,
    Succeeded,
    Failed,
}

public abstract partial class PageViewModelBase(
    VFAdapterWrapper wrapper,
    ISnackNotifyService notifyService) : ObservableObject
{
    protected ISnackNotifyService NotifyService => notifyService;
    protected VFAdapterWrapper Wrapper => wrapper;

    [ObservableProperty]
    private TestResult testResult = TestResult.Pending;

    [ObservableProperty]
    private bool isBusy = false;
    private bool isConnected;

    private readonly List<IRelayCommand> rpcCommands = [];

    protected async Task ExecuteRpcAsync(Func<Task> command)
    {
        IsBusy = true;
        try
        {
            await command();
            TestResult = TestResult.Succeeded;
            notifyService.PushMessage("Operation Succeeded");
        }
        catch (OperationCanceledException)
        {
            TestResult = TestResult.Unknown;
            notifyService.PushMessage("Operation Cancelled");
        }
        catch (VfApiException ex)
        {
            TestResult = TestResult.Failed;
            notifyService.PushMessage(ex.Message);
        }
        catch (Exception ex)
        {
            TestResult = TestResult.Failed;
            notifyService.PushMessage(ex.Message);
        }
        finally
        {
            IsBusy = false;
        }
    }

    protected IAsyncRelayCommand CreateAsyncRpcCommand(Func<Task> command)
    {
        var relayCommand = new AsyncRelayCommand(
                execute: async () => await ExecuteRpcAsync(command),
                canExecute: () => !IsBusy);
        rpcCommands.Add(relayCommand);
        return relayCommand;
    }

    partial void OnIsBusyChanged(bool value)
    {
        foreach (var item in rpcCommands)
        {
            item.NotifyCanExecuteChanged();
        }
    }

    protected void EnsureConnected()
    {
        if (isConnected) return;
        wrapper.StartLinkWithCAD(3);
        isConnected = true;
    }
}
